﻿// SMIL is a community project avaipublic lable under the Microsoft Public License (Ms-PL)
// Code is provided as is and with no warrenty – Use at your own risk
// View the project and the latest code at http://smil.codeplex.com/

using System;
using System.Windows.Media;
using System.Windows.Input;
using Microsoft.Maps.MapControl;

using DeepEarth.BingMapsToolkit.Client.Common.Converters;
using DeepEarth.BingMapsToolkit.Client.Common.Entities;
using DeepEarth.BingMapsToolkit.Client.MapGeometry;

using GeoAPI.Geometries;
using GisSharpBlog.NetTopologySuite.Geometries;
using SMIL.DE.Extensions;

using Location = Microsoft.Maps.MapControl.Location;

namespace SMIL.Geometry
{
    public class FreeDraw : MapPolyline, IDisposable
    {
        
        public event EventHandler OnNoteDone;

        Map parentMap;
        bool isDrawing = false;
        EnhancedMapLayer scratchLayer;

        public FreeDraw(Map _parentMap, EnhancedMapLayer enhancedMapLayer, StyleSpecification style = null)
        {
            parentMap = _parentMap;

            parentMap.MouseLeftButtonUp += parentMap_MouseLeftButtonUp;
            parentMap.MouseLeftButtonDown += parentMap_MouseLeftButtonDown;
            parentMap.MouseMove += parentMap_MouseMove;
            parentMap.Children.Add(this);
            if (style != null)
                StyleSpec = style.Clone();

            SetStyle();

            this.scratchLayer = enhancedMapLayer;
        }

        private void SetStyle()
        {
            //string  = StyleSpec.LineColour;
            Stroke =  new DeepEarth.BingMapsToolkit.Client.Common.Converters.PolyLineColorConverter().Convert(StyleSpec, null, null, null) as SolidColorBrush;
            StrokeThickness = StyleSpec.LineWidth;
        }

        
        StyleSpecification styleSpec;
        public StyleSpecification StyleSpec
        {
            get
            {
                if (null == styleSpec)
                    return new StyleSpecification();
                
                return styleSpec;
            }
            set { styleSpec = value; }
        }

        void parentMap_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            if (isDrawing)
            {
                isDrawing = false;
                parentMap.MousePan += (o, m) => { };

                var lineString = GetGeometry();
                Geometry = lineString;
                StyledGeometry styledGeometry = new StyledGeometry(parentMap, StyleSpec, lineString);
                styledGeometry.RenderNote(scratchLayer);
                if (OnNoteDone != null)
                    OnNoteDone(styledGeometry, null);

                ParentMap.Children.Remove(this);
                Dispose();
            }
        }

        public GeoAPI.Geometries.IGeometry Geometry { get; set; }

        private LineString GetGeometry()
        {
            return new LineString(CoordinateConvertor.LocationCollectionToCoordinates(Locations));
        }

        void parentMap_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (!isDrawing)
            {
                isDrawing = true;
                parentMap.MousePan += parentMap_MousePan;
            }
        }

        void parentMap_MouseMove(object sender, MouseEventArgs e)
        {
            if (isDrawing)
            {
                if (null == Locations)
                    Locations = new LocationCollection();

                this.Locations.Add(parentMap.ViewportPointToLocation(e.GetPosition(parentMap)));
                DeepEarth.BingMapsToolkit.Client.Common.Utilities.AutoPan(e.GetPosition(ParentMap), ParentMap as Microsoft.Maps.MapControl.Core.MapCore);
            }
        }

        void parentMap_MousePan(object sender, MapMouseDragEventArgs e)
        {
            if (isDrawing)
                parentMap.MousePan += (s, ee) => { ee.Handled = true; };
        }

        #region IDisposable Members

        public void Dispose()
        {
            parentMap.MouseLeftButtonUp -= parentMap_MouseLeftButtonUp;
            parentMap.MouseLeftButtonDown -= parentMap_MouseLeftButtonDown;
            parentMap.MouseMove -= parentMap_MouseMove;
        }

        #endregion
    }
}